
// 饿汉模式
class Singleten {
	private static Singleten instance = new Singleten();
	public static Singleten getInstance() {
		return instance;
	}
	private Singleten(){}
}

// 懒汉模式
class Singletenlazy {
	private static Singletenlazy instance = null;
	public static Singletenlazy getInstance() {
		if (instance == null) {
			instance = new Singletenlazy();
		}
		return instance;
	}
	private Singletenlazy(){}
}

// 懒汉模式线程安全：
class Singletenlazy{
	private static volatile Singletenlazy instance = null;
	static Object locker = new Object();
	
	public static Singletenlazy getInstance() {
		if (instance == null) { // 第一个 if 判定是否要加锁
			synchronized(locker) { 
				if (instance == null) {  // 第二个 if 判定是否要创建 instance 实例
					instance = new Singletenlazy();
				}
			}
		}
		return instance;
	}
}

// 静态内部类模式
class Singleten{
	private Singleten(){}
	
	// 静态内部类
	private static class Holder{
		private static final Singleten INSTANCE = new Singleten();
	}
	
	// 对外提供全局访问点
	public static Singleten getInstance() {
		return Holder.INSTANCE;
	}
}

// 枚举
public enum SingletenEnum {
	INSTANCE;
	
	public void doSomething() {
		System.out.println("doSomething")
	}
}
// 调用
SingletenEnum.INSTANCE.doSomething();


// 自己实现一个初级阻塞队列~
class MyBlockingQueue {
	private String elems[] = null;
	private int head;
	private int tail;
	private int size;
	
	Object locker = new Object();
	
	public MyBlockingQueue(int capacity) {
		elems = new String[capacity];
	}
	
	public void put(String elem) {
		synchronized(locker) {
			while (size >= elems.length) {
				locker.wait();
			}
			elems[tail] = elem;
			tail++;
			size++;
			if (tail >= elems.length) {
				tail = 0;
			}
			locker.notifyAll();
		}
	}
	
	public void take() {
		synchronized(locker) {
			while (size == 0) {
				locker.wait();
			}
			String elem = elems[head];
			head++;
			if (head >= elems.length) {
				head = 0;
			}
			size--;
			
			locker.notifyAll();
		}
		return elem;
	}
}

// 升级版 ArrayBlockingQueue
class MyArrayBlockingQueue {
	final ReentrantLock lock = new ReentrantLock();
	
	// 1. 队列不空条件，给消费者用
	private final Condition notEmpty = lock.newCondition();
	// 2. 队列不满条件，给生产者用
	private final Condition notFull = lock.newCondition();
	
	public void put(String elem) {
		lock.lock();
		try {
			while (size == elems.length) {
				// 队列满了，满了，生产者就去“不满”等候室等待
				notFull.await();
			}
			
			// 插入元素...
			elems[tail] = elem;
			tail++;
			size++;
			if (tail >= elems.length) {
				tail = 0;
			}
			
			// 精确唤醒
			notEmpty.signal();
		} finally {
			lock.unlock();
		}
	}
	public void take() {
		lock.lock();
		try {
			while (size == 0) {
				// 队列空了，消费者到“不空”等候室等待
				notEmpty.await();
			}
			
			// 取出元素
			String elem = elems[head];
			head++;
			size--;
            if (head >= elems.length) {
				head = 0;
			}

			//精确唤醒
			notFull.signal();
		} finally {
			lock.unlock();
		}
		return elem;
	}
}

class MyTimerTask implements Comparable<MyTimerTask>{
	private long time;
	private Runnable runnable;
	
	public MyTimerTask (Runnable runnable, long delay) {
		this.runnable = runnable;
		this.time = System.currentTimeMillis() + delay;
	}
	
	public void run() {
		runnable.run();
	}
	
	@Override
	public int compareTo(MyTimerTask o) {
		return (int)(this.time - o.time);
	}
	
	public long getTime() {
		return time;
	}
}

class MyTimer {
	// 扫描任务队列，执行任务的线程
	private Thread t = null;
	
	// 任务队列
	private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
	
	Object locker = new Object();
	
	public void schedule(Runnable runnable, long delay) {
		synchronized(locker) {
			MyTimerTask task = new MyTimerTask(runnable, delay);
			queue.offer(task);
			
			locker.notifyAll();
		}
	}
	
	// 构造方法，创建扫描线程
	public MyTimer() {
		t = new Thread(() -> {
			while(true) {
				synchronized(locker) {
					while (queue.isEmpty()) {
						locker.wait();
					}
					MyTimerTask timeTask = queue.peek();
					long curTime = System.currentTimeMillis();
					if (curTime < timeTask.getTime()) {
						locker.wait(timeTask.getTime() - curTime);
						continue;
					}
					queue.poll();
				}
				timeTask.run();
			}
		});
		t.start();
	}
}


// 自己模拟实现一个线程池~
class MyThreadPoolExecutor{
	
	// 存储线程
	private List<Thread> threadList = new ArrayList<>();
	
	// 任务队列
	private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);
	
	// 通过 n 来指定创建多少个线程
	public MyThreadPoolExecutor(int n) {
		for (int i = 0; i < n; i++) {
			Thread t = new Thread(() -> {
				while (true) {
					// 由于 ArrayBlockingQueue 是线程安全的，此处不需要加锁
					Runnable runnable = queue.take(); // take 是带有阻塞功能的
					runnable.run();
				}
			});
			t.start();
			threadList.add(t);
		}
	}
}

class ThreadDemo{
	public static void main(String[] args) {
		Callable<Integer> callable = new Callable<Integer>() {
			@Override
			public Integer call() {
				int result = 0;
				for (int i = 0; i < 1000; i++) {
					result += i;
				}
				return result;
			}
		}
	}
}